/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 *
 */

import { PoolConstant,WatchEvent } from '@ohos/hvigor';
import {
  compileCodeSnippet,
  getPkgName2SourceRootsMap,
  LogEvent,
  ProjectConfig,
  watch
} from '@ohos/hvigor-arkts-compose';
import { parentPort, workerData } from 'worker_threads';

import { OhosLogger } from '../../utils/log/ohos-logger.js';

import { errorCallback } from './job.js';
import { generateLoaderEnv, onTerminateWorker, setLogLevel } from './util.js';

const updatePkgName2SourceRoots = onTerminateWorker().updatePkgName2SourceRoots;

setLogLevel(workerData.logLevel);
const logger: OhosLogger = OhosLogger.getLogger('Preview_Build');
const projectConfig: ProjectConfig = workerData.projectConfig;
generateLoaderEnv(projectConfig);

const onBuildFailed = (e?: Error | string) => {
  const reason = e instanceof Error ? e.message : (e || 'unknown error');
  parentPort!.postMessage({event: PoolConstant.WORK_ERROR, error: reason});
};

watch(projectConfig, errorCallback, (logs: LogEvent[], lastReUsedFiles?: Set<string>) => {
  updatePkgName2SourceRoots(getPkgName2SourceRootsMap(projectConfig));
  if (lastReUsedFiles) {
    const reUsedLogs = [];
    for (const log of logs) {
      if (parseFileId(log) && log.fileId && lastReUsedFiles.has(log.fileId)) {
        reUsedLogs.push(log);
        parentPort!.postMessage({type: WatchEvent.WATCH_LOG, content: [log]});
      }
    }
    logs.length = 0;
    logs.push(...reUsedLogs);
  } else {
    parentPort!.postMessage({type: WatchEvent.WATCH_LOG, content: logs});
  }
}, parentPort!, logger).then((arkCompileResult) => {
  if (!arkCompileResult.isSuccess) {
    onBuildFailed(arkCompileResult.error);
    return;
  }
  parentPort!.on('message', async (codeSnippet) => {
    const isValidCodeSnippet = codeSnippet && codeSnippet.command && codeSnippet.data && codeSnippet.data.script;
    if (isValidCodeSnippet) {
      compileCodeSnippet(codeSnippet);
    } else {
      logger.debug(`bad codeSnippet ${codeSnippet}`);
    }
  });
  parentPort!.postMessage({event: PoolConstant.WORK_DONE, returnVal: arkCompileResult.compileEvents});
}).catch(reason => {
  onBuildFailed(reason);
}).finally(() => {
  logger.debug('Ark compile finished.');
}); // 启用 rollup watch 和 ts watch

function parseFileId(log: LogEvent): boolean {
  if (typeof log.msg !== 'string') {
    return false;
  }
  const warnPrefix = '[33mArkTS:WARN File: ';
  if (log.msg.startsWith(warnPrefix)) {
    return parse(log.msg.substring(warnPrefix.length));
  }
  const errorPrefix = '[31mArkTS:ERROR File: ';
  if (log.msg.startsWith(errorPrefix)) {
    return parse(log.msg.substring(errorPrefix.length));
  }
  return false;

  function parse(msg: string): boolean {
    const msgList = msg.split('\n');
    let fileMsg = msgList[0];
    for (let i = 0; i < 2; i++) {
      const loc = fileMsg.lastIndexOf(':');
      if (loc === -1) {
        return false;
      }
      fileMsg = fileMsg.substring(0, loc);
    }
    log.fileId = fileMsg;
    return true;
  }
}
